package marshal

import (
	"errors"
	"fmt"
	"reflect"
)

func JsonMarshal(v interface{}) ([]byte, error) {
	json := ""

	switch reflect.TypeOf(v).Kind() {
	case reflect.Struct:
		valueOfV := reflect.ValueOf(v)
		typeOfV := reflect.TypeOf(v)
		for i := 0; i < valueOfV.NumField(); i++ {
			if i != 0 {
				json += ","
			}

			myTag := typeOfV.Field(i).Tag.Get("myTag")
			if myTag != "" {
				json += fmt.Sprintf("%q:", myTag)
			} else {
				json += fmt.Sprintf("%q:", typeOfV.Field(i).Name)
			}

			subJson, err := JsonMarshal(valueOfV.Field(i).Interface())
			if err != nil {
				return []byte(""), err
			}
			json += fmt.Sprintf("%s", subJson)
		}
		json = fmt.Sprintf("{%s}", json)

	case reflect.Array, reflect.Slice:
		arr := reflect.ValueOf(v)
		for i := 0; i < arr.Len(); i++ {
			if i != 0 {
				json += ","
			}
			subJson, err := JsonMarshal(arr.Index(i).Interface())
			if err != nil {
				return []byte(""), err
			}
			json += fmt.Sprintf("%s", string(subJson))
		}
		json = fmt.Sprintf("[%s]", json)

	case reflect.Int, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int8:
		json += fmt.Sprintf("%d", reflect.ValueOf(v).Int())
	case reflect.Float32, reflect.Float64:
		json += fmt.Sprintf("%g", reflect.ValueOf(v).Float())
	case reflect.Bool:
		json += fmt.Sprintf("%t", reflect.ValueOf(v).Bool())
	case reflect.String:
		json += fmt.Sprintf("%q", reflect.ValueOf(v).String())
	default:
		return []byte(""), errors.New(fmt.Sprintf("不支持此类型: %s", reflect.TypeOf(v).Kind()))
	}

	return []byte(json), nil
}
